<?php
/**
* -----------------------------------------------------------------------
* @package VirtueMart
* @subpackage Payment
* @Copyright (C) 2011 Mikkel Elmholdt
*
* @license http://www.gnu.org/copyleft/gpl.html GNU/GPL
* VirtueMart is Free Software.
* VirtueMart comes with absolute no warranty.
*
* www.virtuemart.net
*
* -----------------------------------------------------------------------
*
* This module contains the ps_quickpay class which manages payment
* processing through the Quickpay Payment Gateway (www.quickpay.dk)
*
* The module uses the Quickpay API as described here:
*   http://doc.quickpay.net/api.html
* 
* -----------------------------------------------------------------------
*/


/**
 * This class encapsulates the Quickpay API payment details.
 * It uses the cURL PHP library (http://php.net/manual/en/book.curl.php).
 */
class QuickPayMessage
{
    const QUICKPAY_VERSION = 3;
    const QUICKPAY_SECRET = 'test';
    /**
     * Constructor
     *
     * @param array $message
     */
    public function __construct(Array $message = array())
    {
        foreach ($message as $k => $v) {
            $this->$k = $v;
        }
    }
    
    /**
     * Commits the message to QuickPay
     *
     * @return string
     */
    public function commit()
    {
        $msg = $this->buildMessage();
        $response = $this->transmit($msg);

        // reset variables
        foreach ($this as $k => $v) {
            unset($this->$k);
        }
        
        return $response;
    }
    
    /**
     * Builds a QuickPay message based on class variables set
     *
     * @return array
     */
    private function buildMessage()
    {
        $message = array();
        $md5fields = array(
            'msgtype' => null,
            'merchant' => null,
            'ordernumber' => null,
            'amount' => null,
            'currency' => null,
            'autocapture' => null,
            'cardnumber' => null,
            'expirationdate' => null,
            'cvd' => null,
            'cardtypelock' => null,
            'transaction' => null,
            'description' => null,
            'testmode' => null,
        );
        foreach ($this as $k => $v) {
            $message[$k] = $v;
            
            if (array_key_exists($k, $md5fields)) {
                $md5fields[$k] = $v;
            }
        }
        $md5str = self::QUICKPAY_VERSION . implode('', $md5fields) . QP_MD5_KEY;
        $message['protocol'] = self::QUICKPAY_VERSION;
        $message['md5check'] = md5($md5str);
        
        return $message;
    }
    
    /**
     * Transmits the message to QuickPay
     *
     * @param array $message
     * @return unknown
     */
    private function transmit(Array $message)
    {
        // Create a HTTP POST request with QuickPay message as data
        $url = 'https://secure.quickpay.dk/api';
        $fields = http_build_query($message, false, '&');

        //open connection
        $ch = curl_init();

        //set the url, number of POST vars, POST data
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POST, count($message));
        curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_TIMEOUT, 10);

        /**
         * Enable this option if you are having problems with cURL reporting
         * the error "error setting certificate verify locations" and you
         * are unable to provide a valid CA-cert bundle.
         */
        //curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

        // execute post
        $response = curl_exec($ch);
        
        if (curl_errno($ch)) {
            $result = array(
                'curlstat'  => 1,
                'curlmsg'   => curl_error($ch),
            );
        }
        
        else {
            $result = $this->responseToArray($response);
            $result['curlstat'] = 0;
        }
        
        // close connection
        curl_close($ch);
        
        return $result;
    }
    
    /**
     * Converts QuickPay XML response to an array
     *
     * @param string $response
     * @return array
     */
    private function responseToArray($response)
    {
        // Load XML in response into DOM
        $result = array();
        $dom = new DOMDocument;
        $dom->loadXML($response);

        // Find elements in response and put them in an associative array
        $xpath = new DOMXPath($dom);
        $elements = $xpath->query('/response/*');
        foreach ($elements as $cn) {

            // If the element has (real) children - this is the case for status->history and chstatus->entry
            
            if ($cn->childNodes->length > 1) {
                foreach ($cn->childNodes as $hn) {
                    $result[$cn->nodeName][intval($i) ][$hn->nodeName] = $hn->nodeValue;
                }
                $i++;
            } else {
                $result[$cn->nodeName] = $cn->nodeValue;
            }
        }
        
        return $result;
    }
}

/**
 * The main Quickpay payment class used by Virtuemart.
 */
class ps_quickpay
{
    var $payment_code = "QP";
    
    function show_configuration()
    {
        global $VM_LANG, $mosConfig_live_site;

        $db = new ps_DB;
        /** Read current Configuration ***/
        
        require_once (CLASSPATH . "payment/" . __CLASS__ . ".cfg.php");
?>
    
        <table style="text-align: left;">
        <tr>
            <td><strong><?php
        echo $VM_LANG->_('PHPSHOP_ADMIN_CFG_QP_MERCHANTNUMBER'); ?></strong></td>
            <td>
                <input type="text" name="QP_MERCHANTNUMBER" class="inputbox" value="<?php
        echo QP_MERCHANTNUMBER ?>" />
            </td>
            <td><?php
        echo $VM_LANG->_('PHPSHOP_ADMIN_CFG_QP_MERCHANTNUMBER_EXPLAIN'); ?></td>
        </tr>
        <tr>
            <td><strong><?php
        echo $VM_LANG->_('PHPSHOP_ADMIN_CFG_PAYPAL_STATUS_SUCCESS'); ?></strong></td>
            <td>
                <select name="QP_VERIFIED_STATUS" class="inputbox" >
                <?php
        $q = "SELECT order_status_name,order_status_code FROM #__{vm}_order_status where order_status_code != 'P' ORDER BY list_order";
        $db->query($q);
        $order_status_code = Array();
        $order_status_name = Array();
        while ($db->next_record()) {
            $order_status_code[] = $db->f("order_status_code");
            $order_status_name[] = $db->f("order_status_name");
        }
        for ($i = 0; $i < sizeof($order_status_code); $i++) {
            echo "<option value=\"" . $order_status_code[$i];
            
            if (QP_VERIFIED_STATUS == $order_status_code[$i]) echo "\" selected=\"selected\">";
            else echo "\">";
            echo $order_status_name[$i] . "</option>\n";
        } ?>
                    </select>
            </td>
            <td><?php
        echo $VM_LANG->_('PHPSHOP_ADMIN_CFG_QP_STATUS_SUCCESS_EXPLAIN'); ?>
            </td>
        </tr>
            <tr>
            <td><strong><?php
        echo $VM_LANG->_('PHPSHOP_ADMIN_CFG_QP_STATUS_FAILED'); ?></strong></td>
            <td>
                <select name="QP_INVALID_STATUS" class="inputbox" >
                <?php
        $q = "SELECT order_status_name,order_status_code FROM #__{vm}_order_status ORDER BY list_order";
        $db->query($q);
        $order_status_code = Array();
        $order_status_name = Array();
        while ($db->next_record()) {
            $order_status_code[] = $db->f("order_status_code");
            $order_status_name[] = $db->f("order_status_name");
        }
        for ($i = 0; $i < sizeof($order_status_code); $i++) {
            echo "<option value=\"" . $order_status_code[$i];
            
            if (QP_INVALID_STATUS == $order_status_code[$i]) echo "\" selected=\"selected\">";
            else echo "\">";
            echo $order_status_name[$i] . "</option>\n";
        } ?>
                    </select>
            </td>
            <td><?php
        echo $VM_LANG->_('PHPSHOP_ADMIN_CFG_QP_STATUS_FAILED_EXPLAIN'); ?></td>
        </tr>
        <script language="JavaScript">
          function enableDisableAll() { 
              
            if (document.adminForm.QP_CARDTYPES_0.checked) { 
              document.adminForm.QP_CARDTYPES_1.disabled = true;
              document.adminForm.QP_CARDTYPES_2.disabled = true;
              document.adminForm.QP_CARDTYPES_3.disabled = true;
              document.adminForm.QP_CARDTYPES_4.disabled = true;
              document.adminForm.QP_CARDTYPES_5.disabled = true;
              document.adminForm.QP_CARDTYPES_6.disabled = true;
              document.adminForm.QP_CARDTYPES_7.disabled = true;
              document.adminForm.QP_CARDTYPES_8.disabled = true;
              document.adminForm.QP_CARDTYPES_9.disabled = true;
              document.adminForm.QP_CARDTYPES_10.disabled = true;
              document.adminForm.QP_CARDTYPES_11.disabled = true;
              document.adminForm.QP_CARDTYPES_12.disabled = true;
              document.adminForm.QP_CARDTYPES_13.disabled = true;
              document.adminForm.QP_CARDTYPES_14.disabled = true;
              document.adminForm.QP_CARDTYPES_15.disabled = true;
              document.adminForm.QP_CARDTYPES_16.disabled = true;
              document.adminForm.QP_CARDTYPES_17.disabled = true;
              document.adminForm.QP_CARDTYPES_18.disabled = true;
              
            } else { 
              document.adminForm.QP_CARDTYPES_1.disabled = false;
              document.adminForm.QP_CARDTYPES_2.disabled = false;
              document.adminForm.QP_CARDTYPES_3.disabled = false;
              document.adminForm.QP_CARDTYPES_4.disabled = false;
              document.adminForm.QP_CARDTYPES_5.disabled = false;
              document.adminForm.QP_CARDTYPES_6.disabled = false;
              document.adminForm.QP_CARDTYPES_7.disabled = false;
              document.adminForm.QP_CARDTYPES_8.disabled = false;
              document.adminForm.QP_CARDTYPES_9.disabled = false;
              document.adminForm.QP_CARDTYPES_10.disabled = false;
              document.adminForm.QP_CARDTYPES_11.disabled = false;
              document.adminForm.QP_CARDTYPES_12.disabled = false;
              document.adminForm.QP_CARDTYPES_13.disabled = false;
              document.adminForm.QP_CARDTYPES_14.disabled = false;
              document.adminForm.QP_CARDTYPES_15.disabled = false;
              document.adminForm.QP_CARDTYPES_16.disabled = false;
              document.adminForm.QP_CARDTYPES_17.disabled = false;              
              document.adminForm.QP_CARDTYPES_18.disabled = false;              
            }
          }
        </script>
        <tr>
            <td><strong><?php
        echo $VM_LANG->_('PHPSHOP_ADMIN_CFG_QP_CARDTYPES'); ?></strong></td>
            <td>
                <input type="checkbox" name="QP_CARDTYPES_0" <?php
        
        if (QP_CARDTYPES_0 == '1') echo "checked"; ?> value="1" onclick="javascript:enableDisableAll();"><?php
        echo $VM_LANG->_('PHPSHOP_ALL'); ?> <br>
                <input type="checkbox" name="QP_CARDTYPES_1" <?php
        
        if (QP_CARDTYPES_1 == '1') echo "checked"; ?> value="1">Dankort credit card  <br>
                <input type="checkbox" name="QP_CARDTYPES_2" <?php
        
        if (QP_CARDTYPES_2 == '1') echo "checked"; ?> value="1">Visa credit card (issued in Denmark) <br>
                <input type="checkbox" name="QP_CARDTYPES_3" <?php
        
        if (QP_CARDTYPES_3 == '1') echo "checked"; ?> value="1">Visa Electron credit card<br>
                <input type="checkbox" name="QP_CARDTYPES_4" <?php
        
        if (QP_CARDTYPES_4 == '1') echo "checked"; ?> value="1">Mastercard credit card (issued in Denmark)  <br>
                <input type="checkbox" name="QP_CARDTYPES_5" <?php
        
        if (QP_CARDTYPES_5 == '1') echo "checked"; ?> value="1">Mastercard credit card  <br>
                <input type="checkbox" name="QP_CARDTYPES_6" <?php
        
        if (QP_CARDTYPES_6 == '1') echo "checked"; ?> value="1">Visa Electron credit card (issued in Denmark)<br>
                <input type="checkbox" name="QP_CARDTYPES_7" <?php
        
        if (QP_CARDTYPES_7 == '1') echo "checked"; ?> value="1">JCB credit card  <br>
                <input type="checkbox" name="QP_CARDTYPES_8" <?php
        
        if (QP_CARDTYPES_8 == '1') echo "checked"; ?> value="1">Diners Club credit card (issued in Denmark) <br>
                <input type="checkbox" name="QP_CARDTYPES_9" <?php
        
        if (QP_CARDTYPES_9 == '1') echo "checked"; ?> value="1">MAESTRO (DK)<br>
                <input type="checkbox" name="QP_CARDTYPES_10" <?php
        
        if (QP_CARDTYPES_10 == '1') echo "checked"; ?> value="1">American Express credit card (issued in Denmark)<br>
                <input type="checkbox" name="QP_CARDTYPES_11" <?php
        
        if (QP_CARDTYPES_11 == '1') echo "checked"; ?> value="1">Diners Club credit card  <br>        			
                <input type="checkbox" name="QP_CARDTYPES_12" <?php
        
        if (QP_CARDTYPES_12 == '1') echo "checked"; ?> value="1">American Express credit card  <br>
                <input type="checkbox" name="QP_CARDTYPES_13" <?php
        
        if (QP_CARDTYPES_13 == '1') echo "checked"; ?> value="1">MAESTRO  <br>
                <input type="checkbox" name="QP_CARDTYPES_14" <?php
        
        if (QP_CARDTYPES_14 == '1') echo "checked"; ?> value="1">Forbrugsforeningen af 1886  <br>        			
                <input type="checkbox" name="QP_CARDTYPES_15" <?php
        
        if (QP_CARDTYPES_15 == '1') echo "checked"; ?> value="1">Visa credit card <br>        			
                <input type="checkbox" name="QP_CARDTYPES_16" <?php
        
        if (QP_CARDTYPES_16 == '1') echo "checked"; ?> value="1">Nordea Net Bank <br>
                <input type="checkbox" name="QP_CARDTYPES_17" <?php
        
        if (QP_CARDTYPES_17 == '1') echo "checked"; ?> value="1">Danske Net Bank <br>
                <input type="checkbox" name="QP_CARDTYPES_18" <?php
        
        if (QP_CARDTYPES_18 == '1') echo "checked"; ?> value="1">eDankort credit card  <br>
            </td>
            <td><?php
        echo $VM_LANG->_('PHPSHOP_ADMIN_CFG_QP_CARDTYPES_EXPLAIN'); ?></td>
        </tr>
        <script language="JavaScript">enableDisableAll();</script>
        <tr>
            <td><strong><?php
        echo $VM_LANG->_('PHPSHOP_ADMIN_CFG_QP_LANGUAGE'); ?></strong></td>
            <td>
                <select name="QP_LANGUAGE" class="inputbox">
                <option <?php
        
        if (QP_LANGUAGE == 'da') echo "selected=\"selected\""; ?> value="da">Danish</option>
                <option <?php
        
        if (QP_LANGUAGE == 'en') echo "selected=\"selected\""; ?> value="en">English</option>
                <option <?php
        
        if (QP_LANGUAGE == 'se') echo "selected=\"selected\""; ?> value="se">Swedish</option>
                <option <?php
        
        if (QP_LANGUAGE == 'no') echo "selected=\"selected\""; ?> value="no">Norwegian</option>
                <option <?php
        
        if (QP_LANGUAGE == 'fo') echo "selected=\"selected\""; ?> value="fo">Faeroese</option>
                <option <?php
        
        if (QP_LANGUAGE == 'fr') echo "selected=\"selected\""; ?> value="fr">French</option>
                <option <?php
        
        if (QP_LANGUAGE == 'it') echo "selected=\"selected\""; ?> value="it">Italian</option>
                <option <?php
        
        if (QP_LANGUAGE == 'nl') echo "selected=\"selected\""; ?> value="nl">Dutch</option>
                <option <?php
        
        if (QP_LANGUAGE == 'pl') echo "selected=\"selected\""; ?> value="pl">Polish</option>
                </select>
            </td>
            <td><?php
        echo $VM_LANG->_('PHPSHOP_ADMIN_CFG_QP_LANGUAGE_EXPLAIN'); ?></td>
        </tr>    
        <tr>
            <td><strong><?php
        echo $VM_LANG->_('PHPSHOP_ADMIN_CFG_QP_EMAIL_NOTIFICATION'); ?></strong></td>
            <td>
                <select name="QP_EMAIL_NOTIFICATION" class="inputbox">
                <option <?php
        
        if (QP_EMAIL_NOTIFICATION == '1') echo "selected=\"selected\""; ?> value="1">Yes</option>
                <option <?php
        
        if (QP_EMAIL_NOTIFICATION == '0') echo "selected=\"selected\""; ?> value="0">No</option>        			
                </select>
            </td>
            <td><?php
        echo $VM_LANG->_('PHPSHOP_ADMIN_CFG_QP_EMAIL_EXPLAIN'); ?></td>
        </tr>        
         
        <tr>
            <td><strong><?php
        echo $VM_LANG->_('PHPSHOP_ADMIN_CFG_QP_MD5_KEY'); ?></strong></td>
            <td>
                <input type="text" name="QP_MD5_KEY" class="inputbox" value ="<?php
        echo QP_MD5_KEY; ?>">
            </td>
            <td><?php
        echo $VM_LANG->_('PHPSHOP_ADMIN_CFG_QP_MD5_KEY_EXPLAIN'); ?></td>
        </tr>
        
      </table>
      
      <script language="JavaScript">
                      function resetExtraInfo()
                      {
                              var form = document.adminForm;
                              form.payment_extrainfo.value = "";
                      }
      </script>
      
      <br/><br/>
              

   <?php
        // return false if there\'s no configuration
        return true;
    }
    
    function has_configuration()
    {
        // return false if there's no configuration
        return true;
    }

    /**
     * Returns the "is_writeable" status of the configuration file
     * @param void
     * @returns boolean True when the configuration file is writeable, false when not
     */
    function configfile_writeable()
    {
        return is_writeable(CLASSPATH . "payment/" . __CLASS__ . ".cfg.php");
    }

    /**
     * Returns the "is_readable" status of the configuration file
     * @param void
     * @returns boolean True when the configuration file is writeable, false when not
     */
    function configfile_readable()
    {
        return is_readable(CLASSPATH . "payment/" . __CLASS__ . ".cfg.php");
    }
    
    function get_array_element($arr, $index)
    {
        if (array_key_exists($index, $arr)) return $arr[$index];
        else return '';
    }
    
    /**
     * Writes the configuration file for this payment method
     * @param array An array of objects
     * @returns boolean True when writing was successful
     */
    function write_configuration(&$d)
    {
        global $VM_LANG;

        $my_config_array = array(
            "QP_MERCHANTNUMBER" => $d['QP_MERCHANTNUMBER'],
            "QP_LANGUAGE" => $d['QP_LANGUAGE'],
            "QP_VERIFIED_STATUS" => $d['QP_VERIFIED_STATUS'],
            "QP_INVALID_STATUS" => $d['QP_INVALID_STATUS'],
            "QP_MD5_TYPE" => $this->get_array_element($d, 'QP_MD5_TYPE') ,
            "QP_EMAIL_NOTIFICATION" => $d['QP_EMAIL_NOTIFICATION'],
            "QP_MD5_KEY" => $d['QP_MD5_KEY'],
            "QP_CARDTYPES_0" => $this->get_array_element($d, 'QP_CARDTYPES_0') ,
            "QP_CARDTYPES_1" => $this->get_array_element($d, 'QP_CARDTYPES_1') ,
            "QP_CARDTYPES_2" => $this->get_array_element($d, 'QP_CARDTYPES_2') ,
            "QP_CARDTYPES_3" => $this->get_array_element($d, 'QP_CARDTYPES_3') ,
            "QP_CARDTYPES_4" => $this->get_array_element($d, 'QP_CARDTYPES_4') ,
            "QP_CARDTYPES_5" => $this->get_array_element($d, 'QP_CARDTYPES_5') ,
            "QP_CARDTYPES_6" => $this->get_array_element($d, 'QP_CARDTYPES_6') ,
            "QP_CARDTYPES_7" => $this->get_array_element($d, 'QP_CARDTYPES_7') ,
            "QP_CARDTYPES_8" => $this->get_array_element($d, 'QP_CARDTYPES_8') ,
            "QP_CARDTYPES_9" => $this->get_array_element($d, 'QP_CARDTYPES_9') ,
            "QP_CARDTYPES_10" => $this->get_array_element($d, 'QP_CARDTYPES_10') ,
            "QP_CARDTYPES_11" => $this->get_array_element($d, 'QP_CARDTYPES_11') ,
            "QP_CARDTYPES_12" => $this->get_array_element($d, 'QP_CARDTYPES_12') ,
            "QP_CARDTYPES_13" => $this->get_array_element($d, 'QP_CARDTYPES_13') ,
            "QP_CARDTYPES_14" => $this->get_array_element($d, 'QP_CARDTYPES_14') ,
            "QP_CARDTYPES_15" => $this->get_array_element($d, 'QP_CARDTYPES_15') ,
            "QP_CARDTYPES_16" => $this->get_array_element($d, 'QP_CARDTYPES_16') ,
            "QP_CARDTYPES_17" => $this->get_array_element($d, 'QP_CARDTYPES_17') ,
            "QP_CARDTYPES_18" => $this->get_array_element($d, 'QP_CARDTYPES_18')
        );
        
        $config = "<?php\n";

        //$config .= "defined('_VALID_MOS') or die('Direct Access to this location is not allowed.'); \n\n";
        foreach ($my_config_array as $key => $value) {
            $config.= "define ('$key', '$value');\n";
        }
        $config.= "?>";
        
        if ($fp = fopen(CLASSPATH . "payment/" . __CLASS__ . ".cfg.php", "w")) {
            fputs($fp, $config, strlen($config));
            fclose($fp);

            return true;
        
        } else {
            $d["error"] = $VM_LANG->_('PHPSHOP_ADMIN_CFG_QP_ERR_CONFIGFILE') . " " . CLASSPATH . "payment/" . __CLASS__ . ".cfg.php";
            return false;
        }
    }

    // The complete list of country currency codes.
    function get_iso_code($code)
    {
        switch ($code) {
        case 'ADP':
            return '020';
            break;

        case 'AED':
            return '784';
            break;

        case 'AFA':
            return '004';
            break;

        case 'ALL':
            return '008';
            break;

        case 'AMD':
            return '051';
            break;

        case 'ANG':
            return '532';
            break;

        case 'AOA':
            return '973';
            break;

        case 'ARS':
            return '032';
            break;

        case 'AUD':
            return '036';
            break;

        case 'AWG':
            return '533';
            break;

        case 'AZM':
            return '031';
            break;

        case 'BAM':
            return '977';
            break;

        case 'BBD':
            return '052';
            break;

        case 'BDT':
            return '050';
            break;

        case 'BGL':
            return '100';
            break;

        case 'BGN':
            return '975';
            break;

        case 'BHD':
            return '048';
            break;

        case 'BIF':
            return '108';
            break;

        case 'BMD':
            return '060';
            break;

        case 'BND':
            return '096';
            break;

        case 'BOB':
            return '068';
            break;

        case 'BOV':
            return '984';
            break;

        case 'BRL':
            return '986';
            break;

        case 'BSD':
            return '044';
            break;

        case 'BTN':
            return '064';
            break;

        case 'BWP':
            return '072';
            break;

        case 'BYR':
            return '974';
            break;

        case 'BZD':
            return '084';
            break;

        case 'CAD':
            return '124';
            break;

        case 'CDF':
            return '976';
            break;

        case 'CHF':
            return '756';
            break;

        case 'CLF':
            return '990';
            break;

        case 'CLP':
            return '152';
            break;

        case 'CNY':
            return '156';
            break;

        case 'COP':
            return '170';
            break;

        case 'CRC':
            return '188';
            break;

        case 'CUP':
            return '192';
            break;

        case 'CVE':
            return '132';
            break;

        case 'CYP':
            return '196';
            break;

        case 'CZK':
            return '203';
            break;

        case 'DJF':
            return '262';
            break;

        case 'DKK':
            return '208';
            break;

        case 'DOP':
            return '214';
            break;

        case 'DZD':
            return '012';
            break;

        case 'ECS':
            return '218';
            break;

        case 'ECV':
            return '983';
            break;

        case 'EEK':
            return '233';
            break;

        case 'EGP':
            return '818';
            break;

        case 'ERN':
            return '232';
            break;

        case 'ETB':
            return '230';
            break;

        case 'EUR':
            return '978';
            break;

        case 'FJD':
            return '242';
            break;

        case 'FKP':
            return '238';
            break;

        case 'GBP':
            return '826';
            break;

        case 'GEL':
            return '981';
            break;

        case 'GHC':
            return '288';
            break;

        case 'GIP':
            return '292';
            break;

        case 'GMD':
            return '270';
            break;

        case 'GNF':
            return '324';
            break;

        case 'GTQ':
            return '320';
            break;

        case 'GWP':
            return '624';
            break;

        case 'GYD':
            return '328';
            break;

        case 'HKD':
            return '344';
            break;

        case 'HNL':
            return '340';
            break;

        case 'HRK':
            return '191';
            break;

        case 'HTG':
            return '332';
            break;

        case 'HUF':
            return '348';
            break;

        case 'IDR':
            return '360';
            break;

        case 'ILS':
            return '376';
            break;

        case 'INR':
            return '356';
            break;

        case 'IQD':
            return '368';
            break;

        case 'IRR':
            return '364';
            break;

        case 'ISK':
            return '352';
            break;

        case 'JMD':
            return '388';
            break;

        case 'JOD':
            return '400';
            break;

        case 'JPY':
            return '392';
            break;

        case 'KES':
            return '404';
            break;

        case 'KGS':
            return '417';
            break;

        case 'KHR':
            return '116';
            break;

        case 'KMF':
            return '174';
            break;

        case 'KPW':
            return '408';
            break;

        case 'KRW':
            return '410';
            break;

        case 'KWD':
            return '414';
            break;

        case 'KYD':
            return '136';
            break;

        case 'KZT':
            return '398';
            break;

        case 'LAK':
            return '418';
            break;

        case 'LBP':
            return '422';
            break;

        case 'LKR':
            return '144';
            break;

        case 'LRD':
            return '430';
            break;

        case 'LSL':
            return '426';
            break;

        case 'LTL':
            return '440';
            break;

        case 'LVL':
            return '428';
            break;

        case 'LYD':
            return '434';
            break;

        case 'MAD':
            return '504';
            break;

        case 'MDL':
            return '498';
            break;

        case 'MGF':
            return '450';
            break;

        case 'MKD':
            return '807';
            break;

        case 'MMK':
            return '104';
            break;

        case 'MNT':
            return '496';
            break;

        case 'MOP':
            return '446';
            break;

        case 'MRO':
            return '478';
            break;

        case 'MTL':
            return '470';
            break;

        case 'MUR':
            return '480';
            break;

        case 'MVR':
            return '462';
            break;

        case 'MWK':
            return '454';
            break;

        case 'MXN':
            return '484';
            break;

        case 'MXV':
            return '979';
            break;

        case 'MYR':
            return '458';
            break;

        case 'MZM':
            return '508';
            break;

        case 'NAD':
            return '516';
            break;

        case 'NGN':
            return '566';
            break;

        case 'NIO':
            return '558';
            break;

        case 'NOK':
            return '578';
            break;

        case 'NPR':
            return '524';
            break;

        case 'NZD':
            return '554';
            break;

        case 'OMR':
            return '512';
            break;

        case 'PAB':
            return '590';
            break;

        case 'PEN':
            return '604';
            break;

        case 'PGK':
            return '598';
            break;

        case 'PHP':
            return '608';
            break;

        case 'PKR':
            return '586';
            break;

        case 'PLN':
            return '985';
            break;

        case 'PYG':
            return '600';
            break;

        case 'QAR':
            return '634';
            break;

        case 'ROL':
            return '642';
            break;

        case 'RUB':
            return '643';
            break;

        case 'RUR':
            return '810';
            break;

        case 'RWF':
            return '646';
            break;

        case 'SAR':
            return '682';
            break;

        case 'SBD':
            return '090';
            break;

        case 'SCR':
            return '690';
            break;

        case 'SDD':
            return '736';
            break;

        case 'SEK':
            return '752';
            break;

        case 'SGD':
            return '702';
            break;

        case 'SHP':
            return '654';
            break;

        case 'SIT':
            return '705';
            break;

        case 'SKK':
            return '703';
            break;

        case 'SLL':
            return '694';
            break;

        case 'SOS':
            return '706';
            break;

        case 'SRG':
            return '740';
            break;

        case 'STD':
            return '678';
            break;

        case 'SVC':
            return '222';
            break;

        case 'SYP':
            return '760';
            break;

        case 'SZL':
            return '748';
            break;

        case 'THB':
            return '764';
            break;

        case 'TJS':
            return '972';
            break;

        case 'TMM':
            return '795';
            break;

        case 'TND':
            return '788';
            break;

        case 'TOP':
            return '776';
            break;

        case 'TPE':
            return '626';
            break;

        case 'TRL':
            return '792';
            break;

        case 'TRY':
            return '949';
            break;

        case 'TTD':
            return '780';
            break;

        case 'TWD':
            return '901';
            break;

        case 'TZS':
            return '834';
            break;

        case 'UAH':
            return '980';
            break;

        case 'UGX':
            return '800';
            break;

        case 'USD':
            return '840';
            break;

        case 'UYU':
            return '858';
            break;

        case 'UZS':
            return '860';
            break;

        case 'VEB':
            return '862';
            break;

        case 'VND':
            return '704';
            break;

        case 'VUV':
            return '548';
            break;

        case 'XAF':
            return '950';
            break;

        case 'XCD':
            return '951';
            break;

        case 'XOF':
            return '952';
            break;

        case 'XPF':
            return '953';
            break;

        case 'YER':
            return '886';
            break;

        case 'YUM':
            return '891';
            break;

        case 'ZAR':
            return '710';
            break;

        case 'ZMK':
            return '894';
            break;

        case 'ZWD':
            return '716';
            break;
        }

        // As default return 208 for Danish Kroner
        return '208';
    }

    /**************************************************************************
     ** name: process_payment()
     ** returns:
     ***************************************************************************/
    function process_payment($order_number, $order_total, &$d)
    {
        return true;
    }
    
    /**
     * Handle result from Quickpay API cal.
     */
    private function handleQpResult($result)
    {
        $resultcode = true;
        $errormsg = "";

        if ((int)$result['curlstat'] != 0) {
            $resultcode = false;
            $errormsg = "cURL Error: " . $result['curlmsg'];
        }
        
        elseif ((int)$result['qpstat'] == 0) {
            $chstat = (int)$result['chstat'];
            
            if ($chstat > 0) {
                $resultcode = false;
                $errormsg = "Transaction State Error: " . $result['chstatmsg'];
            }
        }
        
        else {
            $resultcode = false;
            $errormsg = "QuickPay API Error: " . $result['qpstatmsg'];
        }
        
        if ($resultcode == false) {
            echo "<div class=shop_error>";
            echo $errormsg;
            echo "</div>";
        }
        
        return $resultcode;
    }

    /**
     * Capture payment using QuickPay AP
     */
    function capture_payment(&$d)
    {
        if ($d["order_status"] != "S") {
            /* According to Danish law we must not capture the payment 
             * unless the order has been shipped.
             */
            return true;
        }

        require_once (CLASSPATH . "payment/" . __CLASS__ . ".cfg.php");

        $order_id = $d['order_id'];
        $dborder = new ps_DB;
        $dborder->query("SELECT * FROM `#__{vm}_orders` WHERE `order_id` = '" . $dborder->getEscaped($order_id) . "'");
        $dborder->next_record();
        $totalamount = 100 * round($dborder->f("order_total") , 2);

        $dbop = new ps_DB;
        $dbop->query("SELECT `order_payment_trans_id` FROM `#__{vm}_order_payment` WHERE `order_id` = '" . $dbop->getEscaped($order_id) . "'");
        $dbop->next_record();
        $trans_id = $dbop->f('order_payment_trans_id');

        $formdata = array(
            'protocol' => null,
            'msgtype' => 'capture',
            'merchant' => QP_MERCHANTNUMBER,
            'amount' => $totalamount,
            'transaction' => $trans_id,
            'md5check' => null,
        );

        $qpmessage = new QuickPayMessage($formdata);
        $result = $qpmessage->commit();

        return $this->handleQpResult($result);
    }

    /**
     * Cancel payment using QuickPay API
     */
    function void_authorization(&$d)
    {
        require_once (CLASSPATH . "payment/" . __CLASS__ . ".cfg.php");

        $order_id = $d['order_id'];
        $dbop = new ps_DB;
        $dbop->query("SELECT `order_payment_trans_id` FROM `#__{vm}_order_payment` WHERE `order_id` = '" . $dbop->getEscaped($order_id) . "'");
        $dbop->next_record();
        $trans_id = $dbop->f('order_payment_trans_id');
        
        if (empty($trans_id)) {
            // we have no transaction ID yet so we cannot cancel
            return true;
        }
        
        $formdata = array(
            'protocol' => null,
            'msgtype' => 'cancel',
            'merchant' => QP_MERCHANTNUMBER,
            'transaction' => $trans_id,
            'md5check' => null,
        );
        
        $qpmessage = new QuickPayMessage($formdata);
        $result = $qpmessage->commit();
        
        return $this->handleQpResult($result);
    }
    
    /**
     * Refund payment using QuickPay API
     */
    function do_refund(&$d)
    {
        require_once (CLASSPATH . "payment/" . __CLASS__ . ".cfg.php");

        $order_id = $d['order_id'];
        $dborder = new ps_DB;
        $dborder->query("SELECT * FROM `#__{vm}_orders` WHERE `order_id` = '" . $dborder->getEscaped($order_id) . "'");
        $dborder->next_record();
        $totalamount = 100 * round($dborder->f("order_total") , 2);
        $dbop = new ps_DB;
        $dbop->query("SELECT `order_payment_trans_id` FROM `#__{vm}_order_payment` WHERE `order_id` = '" . $dbop->getEscaped($order_id) . "'");
        $dbop->next_record();
        $trans_id = $dbop->f('order_payment_trans_id');
        
        if (empty($trans_id)) {
            // we have no transaction ID yet so we cannot cancel
            return true;
        }
        
        $formdata = array(
            'protocol' => null,
            'msgtype' => 'refund',
            'merchant' => QP_MERCHANTNUMBER,
            'amount' => $totalamount,
            'transaction' => $trans_id,
            'md5check' => null,
        );
        
        $qpmessage = new QuickPayMessage($formdata);
        $result = $qpmessage->commit();
        
        return $this->handleQpResult($result);
    }
}
